using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using IdentityModel;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;

namespace WebGood
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {

            //http 下 登录成功后跳转 http://localhost:port/signin-oidc 时 服务器500错误, 同时 app.UseCookiePolicy(); 不要忘记写
            //services.Configure<CookiePolicyOptions>(options =>
            //{
            //    // This lambda determines whether user consent for non-essential cookies is needed for a given request.
            //    options.CheckConsentNeeded = context => true;
            //    options.MinimumSameSitePolicy = Microsoft.AspNetCore.Http.SameSiteMode.Lax;
            //});
            services.ConfigureNonBreakingSameSiteCookies();

            //services.ConfigureNonBreakingSameSiteCookies();

            //JwtSecurityTokenHandler.DefaultMapInboundClaims = false;

            //https://blog.lcrun.com/wei-shi-yao-yao-shi-yong-jwtsecuritytokenhandler-defaultinboundclaimtypemap-clear/
            JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

            services.AddControllers();

            services.AddAuthentication(options =>
            {
                options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                //options.DefaultChallengeScheme = "oidc";
                options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;//名字随便取  和 AddOpenIdConnect 的 authenticationScheme参数名要一致
            })
              .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
                //.AddOpenIdConnect("oidc", options =>
                .AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
                {
                    options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                    options.Authority = "http://localhost:5000";
                    options.RequireHttpsMetadata = false;

                    options.ClientId = "good_client"; //不能和scope重复
                    options.ClientSecret = "good_secret";
                    //options.ResponseType = "code id_token"; //这个是对的
                    options.ResponseType = OpenIdConnectResponseType.CodeIdToken;
                    options.SaveTokens = true;
                    options.Scope.Clear();
                    options.Scope.Add("api1");
                    options.Scope.Add("good");

                    options.Scope.Add(OidcConstants.StandardScopes.OpenId);
                    options.Scope.Add(OidcConstants.StandardScopes.Profile);
                    options.GetClaimsFromUserInfoEndpoint = true;
                    ////事件
                    //options.Events = new Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectEvents()
                    //{
                    //    //远程故障
                    //    OnRemoteFailure = context =>
                    //    {
                    //        context.Response.Redirect("/");
                    //        context.HandleResponse();
                    //        return Task.FromResult(0);
                    //    },
                    //    //访问拒绝
                    //    OnAccessDenied = context =>
                    //    {
                    //        //重定向到指定页面
                    //        context.Response.Redirect("/");
                    //        //停止此请求的所有处理并返回给客户端
                    //        context.HandleResponse();
                    //        return Task.FromResult(0);
                    //    },
                    //};

                })
                .AddJwtBearer("Bearer", options =>
                {
                    //5004访问5003时的代码, 同时controller写  [Authorize]  => [Authorize(AuthenticationSchemes = "Bearer")] 就可以了
                    //5004来访问5003时, 需要good 权限
                    options.Authority = "http://localhost:5000";
                    options.RequireHttpsMetadata = false;
                    options.Audience = "good";
                });

            ////5004访问5003时的代码
            //services.AddAuthentication("Bearer")//增加这行, 5003自己登陆时, 死循环了,不增加, 5004访问不了
            //    .AddJwtBearer("Bearer", options =>
            //    {
            //        //5004来访问5003时, 需要good 权限
            //        options.Authority = "http://localhost:5000";
            //        options.RequireHttpsMetadata = false;
            //        options.Audience = "good";
            //    });

            //services.AddCors(options =>
            //{
            //    // 这里定义一个 CORS 名为"default"的代理。
            //    options.AddPolicy("default", policy =>
            //    {
            //        policy.WithOrigins("http://localhost:5003")
            //            .AllowAnyHeader()
            //            .AllowAnyMethod();
            //    });
            //});
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            // 在任何其他可能编写cookie的中间件之前添加此项
            app.UseCookiePolicy();//使上面的services.Configure<CookiePolicyOptions>生效

            // This will write cookies, so make sure it's after the cookie policy
            app.UseAuthentication();

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}
